<?php
/**
 * 获取用户信息
 */
function get_user($uid)
{
	global $database;
	$rs = $database->queryFirst("SELECT u.*, ui.avatar FROM user u LEFT JOIN user_info ui ON u.id = ui.user_id  WHERE u.id=".$uid);
	if(isset($rs['id'])){
		return $rs;
	}else{
		return false;
	}
}
/**
 * 评论翻页
 */
function pagination_comment_ajax($page, $length, $total, $link_template) {

if($total>0){

  # 把url转换成标准的字符串，%s%才能替换
  $link_template = urldecode($link_template);

  # 张开的大小
  $available_pages = 4; // 必须为双数
  $start_page = 0;
  $stop_page = 0;

  # 总页数
  $total_pages = ceil($total / $length);
  $first_page = 1;

  if ($page < 1) $page = 1;
  if ($page > $total_pages) $page = $total_pages;
  if ($total_pages <= $available_pages + 4) {
    $start_page = 1;
    $stop_page = $total_pages;
  } else {
    $start_page = $page - ($available_pages / 2);
    if ($start_page < 4) {
      $start_page = 1;
    }
    if ($start_page > $total_pages - ($available_pages + 2)) {
      $start_page = $total_pages - ($available_pages + 2);
    }

    $stop_page = $start_page + $available_pages;
    if ($stop_page < $available_pages + 3) {
      $stop_page = $available_pages + 3;
    }
    if ($stop_page > $total_pages - 3) {
      $stop_page = $total_pages;
    }
  }
  echo "<div class=\"grayr\">";
  //echo "<li>Page $page of $total_pages</li>";

  # 上一页
  if ($page > $first_page) {
    $link = str_replace("%s%", ($page - 1), $link_template);
    //echo "<li><a href=\"$link\"><span class=\"prev\">Prev</span></a></li>";
	echo "<a href=\"javascript:getpage(".($page - 1).")\"> &lt; </a>";
  }else{
    //echo "<li id=\"navprev\"><span class=\"disable\"><span class=\"prev\">Prev</span></span></li>";
	echo "<span class=\"disabled\"> &lt; </span>";
  }

  # 前几页，如果当前页大于3
  if ($start_page > 3) {
    $link = str_replace("%s%", 1, $link_template);
    echo "<a href=\"javascript:getpage(1)\">1</a>";
    $link = str_replace("%s%", 2, $link_template);
    echo "<a href=\"javascript:getpage(2)\">2</a>";
    echo "...";
  }

  for ($i = $start_page; $i <= $stop_page; $i++) {
    $link = str_replace("%s%", $i, $link_template);
    if ($i == $page) {
      echo "<span class=\"current\">$i</span> ";
    } else {
      echo "<a href=\"javascript:getpage(".$i.")\">$i</a>";
    }
  }

  # 如果当前页加上2小于等于最多页
  if ($stop_page < $total_pages - 2) {
    echo "<span>...</span>";
    $link = str_replace("%s%", $total_pages - 1, $link_template);
    echo "<a href=\"javascript:getpage(".($total_pages - 1).")\">".($total_pages - 1)."</a>";
    $link = str_replace("%s%", $total_pages, $link_template);
    echo "<a href=\"javascript:getpage(".$total_pages.")\">$total_pages</a>";
  }

  # 下一页
  if ($page < $total_pages) {
    $link = str_replace("%s%", ($page + 1), $link_template);
    //echo "<li><a href=\"{$link}\"><span class=\"next\">Next</span></a></li>";
	echo "<a href=\"javascript:getpage(".($page + 1).")\"> &gt; </a>";
  } else {
    //echo "<li id=\"navnext\"><span class=\"disable\"><span class=\"next\">Next</span></span></li>";
	echo "<span class=\"disabled\"> &gt; </span>";
  }
  echo "</div>";
}
}

/**
 * 载入model
 */
function load_model($model)
{
	foreach($model as $file){
		include_once(_CONST_LOCAL_INCLUDE_PATH . 'model/' . $file . '.php');
	}
}

function is_mature($genres) {
	if (
		preg_match("/Lolicon/", $genres) ||
		preg_match("/Shotacon/", $genres) ||
		preg_match("/Adult/", $genres) ||
		preg_match("/Yaoi/", $genres) ||
		preg_match("/Yuri/", $genres) ||
		preg_match("/Mature/", $genres) ||
		preg_match("/Ecchi/", $genres) ||
		preg_match("/Smut/", $genres)
	) {
		return true;
	}
	return false;
}

function is_sex($genres) {
	if (
		preg_match("/Lolicon/", $genres) ||
		preg_match("/Shotacon/", $genres) ||
		preg_match("/Adult/", $genres)
	) {
		return true;
	}
	return false;
}

function is_forbidden($genres) {
	if (
		preg_match("/Lolicon/", $genres) ||
		preg_match("/Shotacon/", $genres)
	) {
		return true;
	}
	return false;
}

function simplify_name($name) {
	$name = preg_replace("/[^0-9a-z]/i", " ", $name);
	$name = preg_replace("/ +/i", " ", $name);
	return trim($name);
}

/**
 * 判断用户是否登录
 *
 * @return boolean
 */
function is_loggedin() {
  if (isset($_SESSION['userid']) && $_SESSION['userid'] > 0)
    return true;
  return false;
}

/**
 * 判断用户未登录跳转
 *
 * @return boolean
 */
function check_loggedin() {
  if (isset($_SESSION['userid']) && $_SESSION['userid'] > 0){
    return true;
  }else{ 	
	header("Location:" . _CONST_WEB_URL . 'login.php');
  }
}

/**
 * 判断后台用户是否登录
 *
 * @return boolean
 */
function is_backend_loggedin() {
  global $user;
  if (is_array($user) && $user['buserid'] > 0)
    return true;
  return false;
}

/**
 * 高级if
 *
 * @param unknown_type $expression
 * @param unknown_type $true
 * @param unknown_type $false
 * @return unknown
 */
function iif($expression, $true, $false = '') {
  if ($expression == 0) {
    return $false;
  } else {
    return $true;
  }
}

/**
 * 整理manga name 成为url形式
 *
 * @param unknown_type $name
 * @return unknown
 */
function reformat_manga_name($name) {
  $name = preg_replace("/[^a-z0-9]+/", "_", strtolower($name));
  $name = preg_replace("/^_+|_+$/", "", strtolower($name));
  $name = preg_replace("/_+/", "_", strtolower($name));
  return $name;
}

/**
 * 重新整理 章节
 *
 * @param unknown_type $in
 * @param unknown_type $name
 * @return unknown
 */
function reformat_volch($in, $name = '') {
  list($vol, $no) = unpack_volch($in);
  return iif($vol != '', "Vol.$vol ")."Ch.".str_replace(".0", "", $no).iif($name != '', htmlspecialchars(": ".$name));
}

/**
 * 重新整理 章节
 *
 * @param unknown_type $in
 * @param unknown_type $name
 * @return unknown
 */
//add by lanyg 2011-01-20
function reformat_ch($in) {
  list($vol, $no) = unpack_volch($in);
  $no = ($no=="000")? "0" : preg_replace('/^[0]+/','',$no);
  return str_replace(".0", "", $no);
}

/**
 * 章节号压缩
 *
 * @param unknown_type $vol
 * @param unknown_type $no
 * @return unknown
 */
function pack_volch($vol, $no) {
  $no = $no + 0;
  $no = sprintf("%05.1f", $no);

  if (is_numeric($vol) && intval($vol) < 10) {
    $vol = '0'.intval($vol);
  }

  return iif($vol != "" && strlen($vol) <= 3, strtoupper($vol)."-").$no;
}

/**
 * 章节号 解压缩
 *
 * @param unknown_type $in
 * @return unknown
 */
function unpack_volch($in) {
  $_tmp = explode("-", $in);
  if (sizeof($_tmp) == 2) {
    return $_tmp;
  } else {
    $volume = '';
    $no = $_tmp[0];
    return array($volume, $no);
  }
}

/**
 * 切开字符串
 *
 * @param unknown_type $string
 * @param unknown_type $length
 * @return unknown
 */
function cut_string($string, $length) {
  $len = strlen($string);

  if ($len > $length) {
    $part_len = round(($length - 5) / 4);
    $string = substr($string, 0, $part_len * 3)." ... ".substr($string, -$part_len, $part_len);
  }

  return $string;
}

/**

 */
function cache_header($expires = 900) {
  @header('Last-Modified: '.@gmdate("D, d M Y H:i:s", floor(@time() / $expires) * $expires).' GMT');
  @header('Cache-Control: max-age='.$expires.', must-revalidate');
  @header('Expires: '.@gmdate("D, d M Y H:i:s", @time() + $expires).' GMT');
}

function no_cache_header() {
  header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
  header("Pragma: no-cache");
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
}

/**
 * 比较时间
 *
 * @param unknown_type $t
 * @param unknown_type $format
 * @return unknown
 */
function get_diff_date($time, $format = "") {
  $now = time();

  if ($time + 86400 > $now) {
    return "今天";
  } else if ($time + 172800 > $now) {
    return "昨天";
  }

  if ($format == "") {
    $format = _CONST_DATE_FORMAT;
  }

  return date($format, $time + _CONST_TIME_OFFSET * 3600);
}

function convert_date($time, $format = "") {
  if ($format == "") {
    $format = _CONST_DATE_FORMAT." "._CONST_TIME_FORMAT;
  }

  if ($time)
    return @date($format, $time + _CONST_TIME_OFFSET * 3600);
  else
    return "n/a";
}

/**
 * 把字符串换成mysql形式
 */
function string_sql($string) {
    if ($string == "" and $string != 0) {
        return 'NULL';
    } else {
        return "'".addslashes($string)."'";
    }
}

/**
 * 把string换成file形式 引号前加\
 */
function string_file($string) {
  return str_replace("\"", "\\\"", $string);
}

/**
 * 设置cookies
 *
 * @param unknown_type $name
 * @param unknown_type $value
 * @param unknown_type $expire
 */
function set_cookie($name, $value = "", $expire = 0) {
  if (_CONST_COOKIE_DOMAIN && _CONST_COOKIE_SECURE) {
    setcookie($name, $value, $expire, _CONST_COOKIE_PATH, _CONST_COOKIE_DOMAIN, _CONST_COOKIE_SECURE);
  } else if (_CONST_COOKIE_DOMAIN) {
    setcookie($name, $value, $expire, _CONST_COOKIE_PATH, _CONST_COOKIE_DOMAIN);
  } else {
    setcookie($name, $value, $expire, _CONST_COOKIE_PATH);
  }
}

function is_checked($check) { return iif($check, 'checked="checked"'); }
function is_selected($check) { return iif($check, 'selected="selected"'); }

/**
 * 计算字节数
 *
 * @param unknown_type $size
 * @return unknown
 */
function file_size($size) {
  if ($size > 1024*1024) {
    return sprintf("%01.2f MB", ($size/1024)/1024);
  } else if ($size > 1024) {
    return sprintf("%01.2f KB", $size/1024);
  } else {
    return $size." Bytes";
  }
}

/**
 * 页面跳转
 */
function redirect($message) {
  ?>
  <html>
  <head>
  <title>Redirecting</title>
  <meta http-equiv="Refresh" content="1;url=<?= $_REQUEST['referrer'] ?>" />
  </head>
  <body>
  <h2>Redirecting...</h2>
  <p><?= $message ?></p>
  <p><a>Click here if your browser does not automatically redirect you.</a></p>
  </body>
  </html>
  <?
  exit();
}

/**
 * 页面跳转
 */
function error($errorcode, $message) {
  global $database;
  switch ($errorcode) {
    case 403:
      include_once(_CONST_LOCAL_LAYOUT_PATH."403.php");
      break;
    case 404:
    default:
      include_once(_CONST_LOCAL_LAYOUT_PATH."404.php");
  case 200:
      include_once(_CONST_LOCAL_LAYOUT_PATH."200.php");
      break;
  }
  exit();
}

/**
 * 后台验证表单
 *
 * @param unknown_type $field
 * @param unknown_type $title
 * @param unknown_type $type
 * @param unknown_type $arg
 * @return unknown
 */
function verify_field($field, $title, $type, $arg = '') {
  global $error_strs;

  $value = $_REQUEST[$field];

  switch ($type) {
    case "empty":
      if (trim($value) == "") {
        $error_strs[$field] = "missing";
        return false;
      }
      break;
    case "maxlength":
      if (strlen($value) > $arg) {
        $error_strs[$field] = "limited to $arg characters";
        return false;
      }
      break;
    case "minlength":
      if (strlen($value) < $arg) {
        $error_strs[$field] = "least $arg characters";
        return false;
      }
      break;
    case "number_only":
      if (!is_numeric(trim($value))) {
        $error_strs[$field] = "number only";
        return false;
      }
      break;
    case "custom":
      if (!preg_match($arg, trim($value))) {
        $error_strs[$field] = "invalid format";
        return false;
      }
      break;
    case "email":
      if (!is_email($value)) {
        $error_strs[$field] = "invalid format";
        return false;
      }
      break;
	case "url":
      if (!is_url($value)) {
        $error_strs[$field] = "invalid format";
        return false;
      }
      break;  
  }

  return true;
}

/**
 * is_mail
 *
 * @param string $email
 * @return boolean
 */
function is_email($email){  
	return strlen($email) > 6 && preg_match("/^[\w\-\.]+@[\w\-]+(\.\w+)+$/", $email);  
}

/**
 * is_url
 *
 * @param string $str
 * @return boolean
 */
function is_url($str){  
	return preg_match("/^(http|https):\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"])*$/", $str);   
} 

/**
 * 后台提示输入错误
 *
 * @param unknown_type $field
 * @return unknown
 */
function show_field_error($field) {
  global $error_strs;
  if ($error_strs[$field] != "") {
    return "<strong><span>".$error_strs[$field]."</span></strong>";
  }
}

/**
 * 前台提示输入错误
 *
 * @param unknown_type $field
 * @return unknown
 */
function show_error($field) {
  global $error_strs;
  if ($error_strs[$field] != "") {
    return "<span class=\"error\" for=\"".$field."\" generated=\"true\">".$error_strs[$field]."</span>";
  }
}

/**
 * 递归删除目录
 *
 * @param unknown_type $directory
 * @param unknown_type $empty
 * @return unknown
 */
function recursive_remove_directory($directory, $empty = false) {
  if (substr($directory, -1) == '/') {
    $directory = substr($directory, 0, -1);
  }
  if (!file_exists($directory) || !is_dir($directory)) {
    return false;
  } elseif (is_readable($directory)) {
    $handle = opendir($directory);
    while (false !== ($item = readdir($handle))) {
      if ($item != '.' && $item != '..') {
        $path = $directory.'/'.$item;
        if (is_dir($path))  {
            recursive_remove_directory($path);
        } else {
            unlink($path);
        }
      }
    }
    closedir($handle);
    if ($empty == false) {
      if (!rmdir($directory)) {
          return false;
      }
    }
  }
  return true;
}

/**
 * 整理IP
 *
 * @return unknown
 */
function fetch_alt_ip() {
  $alt_ip = $_SERVER['REMOTE_ADDR'];

  if (isset($_SERVER['HTTP_CLIENT_IP'])) {
    $alt_ip = $_SERVER['HTTP_CLIENT_IP'];
  } else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
    // make sure we dont pick up an internal IP defined by RFC1918
    foreach ($matches[0] as $ip) {
      if (!preg_match("#^(10|172\.16|192\.168)\.#", $ip)) {
        $alt_ip = $ip;
        break;
      }
    }
  } else if (isset($_SERVER['HTTP_FROM'])) {
    $alt_ip = $_SERVER['HTTP_FROM'];
  }

  return $alt_ip;
}

/**
* Strips away [quote] tags and their contents from the specified string
*
* @param	string	Text to be stripped of quote tags
*
* @return	string
*/
function strip_quotes($text) {
	$lowertext = strtolower($text);

	// find all [quote tags
	$start_pos = array();
	$curpos = 0;
	do {
		$pos = strpos($lowertext, '[quote', $curpos);
		if ($pos !== false AND ($lowertext[$pos + 6] == '=' OR $lowertext[$pos + 6] == ']')) {
			$start_pos["$pos"] = 'start';
		}

		$curpos = $pos + 6;
	} while ($pos !== false);

	if (sizeof($start_pos) == 0) {
		return $text;
	}

	// find all [/quote] tags
	$end_pos = array();
	$curpos = 0;
	do {
		$pos = strpos($lowertext, '[/quote]', $curpos);
		if ($pos !== false) {
			$end_pos["$pos"] = 'end';
			$curpos = $pos + 8;
		}
	} while ($pos !== false);

	if (sizeof($end_pos) == 0) {
		return $text;
	}

	// merge them together and sort based on position in string
	$pos_list = $start_pos + $end_pos;
	ksort($pos_list);

	do {
		// build a stack that represents when a quote tag is opened
		// and add non-quote text to the new string
		$stack = array();
		$newtext = '';
		$substr_pos = 0;
		foreach ($pos_list as $pos => $type) {
			$stacksize = sizeof($stack);
			if ($type == 'start') {
				// empty stack, so add from the last close tag or the beginning of the string
				if ($stacksize == 0) {
					$newtext .= substr($text, $substr_pos, $pos - $substr_pos);
				}
				array_push($stack, $pos);
			} else {
				// pop off the latest opened tag
				if ($stacksize) {
					array_pop($stack);
					$substr_pos = $pos + 8;
				}
			}
		}

		// add any trailing text
		$newtext .= substr($text, $substr_pos);

		// check to see if there's a stack remaining, remove those points
		// as key points, and repeat. Allows emulation of a non-greedy-type
		// recursion.
		if ($stack) {
			foreach ($stack as $pos) {
				unset($pos_list["$pos"]);
			}
		}
	} while ($stack);

	return $newtext;
}

/**
* Strips away bbcode from a given string, leaving plain text
*
* @param	string	Text to be stripped of bbcode tags
* @param	boolean	If true, strip away quote tags AND their contents
* @param	boolean	If true, use the fast-and-dirty method rather than the shiny and nice method
*
* @return	string
*/
function strip_bbcode($message, $stripquotes = false, $fast_and_dirty = false, $showlinks = true) {
	$find = array();
	$replace = array();

	if ($stripquotes) {
		// [quote=username] and [quote]
		$message = strip_quotes($message);
	}

	// a really quick and rather nasty way of removing vbcode
	if ($fast_and_dirty) {
		// any old thing in square brackets
		$find[] = '#\[.*/?\]#siU';
		$replace[] = '';

		$message = preg_replace($find, $replace, $message);
	} else {
		// simple links
		$find[] = '#\[(email|url)=("??)(.+)\\2\]\\3\[/\\1\]#siU';
		$replace[] = '\3';

		// named links
		$find[] = '#\[(email|url)=("??)(.+)\\2\](.+)\[/\\1\]#siU';
		$replace[] = ($showlinks ? '\4 (\3)' : '\4');

		// replace links (and quotes if specified) from message
		$message = preg_replace($find, $replace, $message);

		// strip out all other instances of [x]...[/x]
		while(preg_match_all('#\[(\w+?)(?>[^\]]*?)\](.*)(\[/\1\])#siU', $message, $regs)) {
			foreach($regs[0] AS $key => $val) {
				$message  = str_replace($val, $regs[2]["$key"], $message);
			}
		}
		$message = str_replace('[*]', ' ', $message);
	}

	return trim($message);
}

function shortcut($string, $length) {
	if (advstrlen($string) > $length) {
		return trim(advchop($string, $length))."...";
	} else {
		return trim($string);
	}
}

/**
* Converts html entities to a regular character so strlen can be performed
*
* @param	string	String to be measured
*/
function advstrlen($string) {
	$string = preg_replace('#&\#([0-9]+);#', '_', $string);

	if (function_exists('mb_strlen') AND $length = @mb_strlen($string, 'utf-8')) {
		return $length;
	} else {
		return strlen($string);
	}
}

/**
* Chops off a string at a specific length, counting entities as once character
* and using multibyte-safe functions if available.
*
* @param  string  String to chop
* @param  integer Number of characters to chop at
*
* @return string  Chopped string
*/
function advchop($string, $length) {
  $length = intval($length);
  if ($length <= 0) {
    return $string;
  }

  if (preg_match_all('/&(#[0-9]+|lt|gt|quot|amp);/', $string, $matches, PREG_OFFSET_CAPTURE)) {
    // find all entities because we need to count them as 1 character
    foreach ($matches[0] AS $match) {
      $entity_length = strlen($match[0]);
      $offset = $match[1];

      // < since length starts at 1 but offset starts at 0
      if ($offset < $length) {
        // this entity happens in the chop area, so extend the length to include this
        // -1  since the entity should still count as 1 character
        $length += strlen($match[0])  - 1;
      } else {
        break;
      }
    }
  }

  if (function_exists('mb_substr') AND ($substr = @mb_substr($string, 0, $length, 'utf-8')) != '') {
    return $substr;
  } else{
    return substr($string, 0, $length);
  }
}

/**
 * 生成manga连接
 */
function make_manga_url($manga_name) {
  return "manga/".reformat_manga_name($manga_name)."/";
}
/**
 * 生成chapterurl
 */
function make_chapter_url($manga_name, $volume_chapter) {
  #name
  $url = "manga/".reformat_manga_name($manga_name)."/";

  # volume
  $vc = unpack_volch($volume_chapter);
  if ($vc[0] != "") {
    $url .= "v".$vc[0]."/";
  }

  # chapter
  $tmp = explode(".", $vc[1]);
  if ($tmp[1] == 0) {
    $url .= "c".$tmp[0]."/";
  } else {
    $url .= "c".$vc[1]."/";
  }

  return $url;
}

/**
 * 通用的翻页函数
 * 用于前台！
 */
function pagination($page, $length, $total, $link_template) {
  # 把url转换成标准的字符串，%s%才能替换
  $link_template = urldecode($link_template);

  # 张开的大小
  $available_pages = 4; // 必须为双数
  $start_page = 0;
  $stop_page = 0;

  # 总页数
  $total_pages = ceil($total / $length);
  $first_page = 1;

  if ($page < 1) $page = 1;
  if ($page > $total_pages) $page = $total_pages;
  if ($total_pages <= $available_pages + 4) {
    $start_page = 1;
    $stop_page = $total_pages;
  } else {
    $start_page = $page - ($available_pages / 2);
    if ($start_page < 4) {
      $start_page = 1;
    }
    if ($start_page > $total_pages - ($available_pages + 2)) {
      $start_page = $total_pages - ($available_pages + 2);
    }

    $stop_page = $start_page + $available_pages;
    if ($stop_page < $available_pages + 3) {
      $stop_page = $available_pages + 3;
    }
    if ($stop_page > $total_pages - 3) {
      $stop_page = $total_pages;
    }
  }

  //echo "<ul>";
  //echo "<li>Page $page of $total_pages</li>";

  # 上一页
  if ($page > $first_page) {
    $link = str_replace("%s%", ($page - 1), $link_template);
    echo "<a href=\"$link\"> < </a>";
  }else{
    echo "<span class=\"disabled\"> < </span>";
  }

  # 前几页，如果当前页大于3
  if ($start_page > 3) {
    $link = str_replace("%s%", 1, $link_template);
    echo "<a href=\"{$link}\">1</a>";
    $link = str_replace("%s%", 2, $link_template);
    echo "<a href=\"{$link}\">2</a>";
    echo "...";
  }

  for ($i = $start_page; $i <= $stop_page; $i++) {
    $link = str_replace("%s%", $i, $link_template);
    if ($i == $page) {
      echo "<span class=\"current\">$i</span> ";
    } else {
      echo "<a href=\"{$link}\">$i</a>";
    }
  }

  # 如果当前页加上2小于等于最多页
  if ($stop_page < $total_pages - 2) {
    echo "...";
    $link = str_replace("%s%", $total_pages - 1, $link_template);
    echo "<a href=\"{$link}\">".($total_pages - 1)."</a>";
    $link = str_replace("%s%", $total_pages, $link_template);
    echo "<a href=\"{$link}\">$total_pages</a>";
  }

  # 下一页
  if ($page < $total_pages) {
    $link = str_replace("%s%", ($page + 1), $link_template);
    echo "<a href=\"{$link}\"> > </a>";
  } else {
    echo "<span class=\"disabled\"> > </span>";
  }
  //echo "</ul>";
}

function st($i) {
  switch(floor($i/10) % 10) {
    default:
      switch( $i % 10 ) {
        case 1: return 'st';
        case 2: return 'nd';
        case 3: return 'rd';
      }
    case 1:
  }
  return 'th';
}

function get_series($series_code) {
  global $database;

  if (!preg_match("/^([a-z0-9_]+)$/", $series_code)) {
    return false;
  }

  #调用缓冲
//  include_once(_CONST_CACHE_PATH."mangaArraybyUrl.php");
//  $series_id = $mangaArraybyUrl[$series_code]["series_id"];
//  if (!is_numeric($series_id)) {
    $sql = "SELECT ms.*, mc.no FROM manga_series ms LEFT JOIN manga_chapters mc ON mc.chapter_id = ms.last_chapter_id WHERE ms.series_code = ".string_sql($series_code);
    $_series = $database->queryFirst($sql, 600);
//  } else {
//    $sql = "SELECT ms.*, mc.no FROM manga_series ms LEFT JOIN manga_chapters mc ON mc.chapter_id = ms.last_chapter_id WHERE ms.series_id = ".$series_id;
//    $_series = $database->queryFirst($sql, 600);
//  }

  if (!$_series['series_id']) {
    $sql = "SELECT i.series_name alia_name, i.series_code alia_code, ms.series_code orig_code, ms.name orig_name, ms.*, mc.no FROM index_series i LEFT JOIN manga_series ms ON ms.series_id = i.series_id LEFT JOIN manga_chapters mc ON mc.chapter_id = ms.last_chapter_id WHERE i.series_code = ".string_sql($series_code);
    $_series = $database->queryFirst($sql, 600);
  }

  if ($_series['series_id'] > 0) {
    return $_series;
  } else {
    return false;
  }
}

function get_series_by_id($series_id) {
  global $database;

  $series_id = intval($series_id);

  if (!$series_id) {
    return false;
  }

  $sql = "SELECT ms.*, mc.no FROM manga_series ms LEFT JOIN manga_chapters mc ON mc.chapter_id = ms.last_chapter_id WHERE ms.series_id = ".$series_id;
  $_series = $database->queryFirst($sql, 600);
  if ($_series['series_id'] > 0) {
    return $_series;
  } else {
    return false;
  }
}

function update_total_chapters($series_id) {
	global $database;

	if (intval($series_id) < 1)
		return false;

	$sql = "SELECT count(*) total_chapters FROM manga_chapters WHERE series_id = ".$series_id." AND is_online = 1";
	$row = $database->queryFirst($sql, 120);
	$total_chapters = $row['total_chapters'];

	if ($total_chapters > 0) {
		$sql = "UPDATE LOW_PRIORITY manga_series SET total_chapters = $total_chapters WHERE series_id = $series_id";
		$database->execute($sql);
	} else {
		return false;
	}

	return $total_chapters;
}

function update_total_pages($chapter_id) {
	global $database;

	if (intval($chapter_id) < 1)
		return false;

	$sql = "SELECT count(*) total_pages FROM manga_scans WHERE is_available != 0 AND chapter_id = ".$chapter_id." ORDER BY file_name ASC";
	$row = $database->queryFirst($sql, 120);
	$total_pages = $row['total_pages'];

	if ($total_pages > 0) {
		$sql = "UPDATE LOW_PRIORITY manga_chapters SET total_pages = $total_pages WHERE chapter_id = $chapter_id";
		$database->execute($sql);
	} else {
		return false;
	}

	return $total_pages;
}

function create_manga_cache() {
  global $database;

  $sql = "SELECT series_id, name FROM manga_series WHERE is_online = 1 AND is_hidden = 0 ORDER BY name ASC";
  $database->execute($sql);

  $out = "<?\n";
  $out2 = "<?\n";

  $out.= "\$mangaArraybyID = array(\n";
  $out2.= "\$mangaArraybyUrl = array(\n";
  $js = "var series_list = new Array(\n";

  $total_series = $database->getNumRows();

  if ($total_series > 0) {
    while ($r = $database->getRecord()) {
      $out .= "\"{$r["series_id"]}\"=>array(\n";
      $out2 .= "\"".reformat_manga_name($r["name"])."\"=>array(\n";

      $out .= "\"name\"=>\"".string_file($r["name"])."\",\n";
      $out .= "\"urlname\"=>\"".reformat_manga_name($r["name"])."\"\n";

      $out2 .= "\"series_id\"=>\"".$r["series_id"]."\",\n";
      $out2 .= "\"name\"=>\"".string_file($r["name"])."\"\n";

      $out .= "),\n";
      $out2 .= "),\n";

      $js .= "[\"".htmlspecialchars($r["name"])."\",\"".$r["series_id"]."\"],\n";
    }

    $out = substr($out, 0, -2)."\n";
    $out2 = substr($out2, 0, -2)."\n";
    $js = substr($js, 0, -2)."\n";
  }

  $out.= ");\n?>";
  $out2.= ");\n?>";
  $js .= ");\n\nvar total_series = $total_series;\n\n";

  $js .= "function addSeriesList(id,val){\n";
  $js .= "for(var i=0;i<total_series;i++){\n";
  $js .= "document.getElementById(id).options[i]=new Option(series_list[i][0], series_list[i][1]);\n";
  $js .= "}\n";
  $js .= "document.getElementById(id).value=val;\n";
  $js .= "}\n";

  #文件写入类
  include_once(_CONST_LOCAL_INCLUDE_PATH."filewriter.class.php");
  FileWriter::f_xwrite(_CONST_CACHE_PATH."mangaArraybyID.php",$out);
  FileWriter::f_xwrite(_CONST_CACHE_PATH."mangaArraybyUrl.php",$out2);
  FileWriter::f_xwrite(_CONST_CACHE_PATH."series_list.js",$js);
}

function get_nav_chapters($series_id, $chapter_id) {
	global $database;
	$series_id = intval($series_id);
	if ($series_id <= 0)
		return false;

	$chapter_id = intval($chapter_id);
	if ($chapter_id <= 0)
		return false;

	$sql = "SELECT chapter_id, no FROM manga_chapters WHERE series_id='$series_id' ORDER BY no ASC";
  $chapter_rs = $database->queryArray($sql);

	$prev_ch = null;
	$next_ch = null;

	$total_chapters = sizeof($chapter_rs);
	if ($total_chapters > 0) {
		for ($j = 0; $j < $total_chapters; $j++) {
			if ($chapter_rs[$j]['chapter_id'] == $chapter_id) {
				if ($j>0) $prev_ch = $chapter_rs[$j - 1];
				if ($j<($total_chapters-1)) $next_ch = $chapter_rs[$j + 1];
				return array($prev_ch, $next_ch);
			}
		}
	}
	return false;
}

function create_chapters_cache($series_id, $series_name) {
  global $database;
  $series_id = intval($series_id);
  if ($series_id <= 0)
    return false;

  $sql = "SELECT chapter_id, no, name FROM manga_chapters WHERE series_id='$series_id' ORDER BY no ASC";
  $chapter_rs = $database->queryArray($sql);

  $series_dir = _CONST_CACHE_PATH."manga/".reformat_manga_name($series_name);
  #创建目录
  FileWriter::MakeDir($series_dir);

  $php = "<?php\n";
  $php .= "\$chapter_cache = array(\n";

  $js = "var chapter_list = new Array(\n";

  $total_chapters = sizeof($chapter_rs);

  if ($total_chapters > 0) {
    for ($j = 0; $j < $total_chapters - 1; $j++) {
      $php .= "  \"{$chapter_rs[$j]["no"]}\"=>\"{$chapter_rs[$j]["chapter_id"]}\",\n";
      $vc = unpack_volch($chapter_rs[$j]["no"]);
      $js .= "  [\"".reformat_volch($chapter_rs[$j]['no'], $chapter_rs[$j]['name'])."\",\"".iif($vc[0] != "", "v$vc[0]/")."c".preg_replace("/\.0$/i", "", $vc[1])."\""."],\n";
    }

    $j = $total_chapters - 1;
    $php .= "  \"{$chapter_rs[$j]["no"]}\"=>\"{$chapter_rs[$j]["chapter_id"]}\"\n";
    $vc = unpack_volch($chapter_rs[$j]["no"]);
    $js .= "  [\"".reformat_volch($chapter_rs[$j]['no'], $chapter_rs[$j]['name'])."\",\"".iif($vc[0] != "", "v$vc[0]/")."c".preg_replace("/\.0$/i", "", $vc[1])."\""."]\n";
  }

  $php .= ");\n\n\$total_chapters = $total_chapters;\n?>";

  $js .= ");\n\nvar total_chapters = $total_chapters;\n\n";

  $js .= "for (var i = 0; i < chapter_list.length; i++) {\n";
	$js .= "  document.getElementById('top_chapter_list').options[i] = new Option(chapter_list[i][0], chapter_list[i][1]);\n";
  $js .= "  document.getElementById('bottom_chapter_list').options[i] = new Option(chapter_list[i][0], chapter_list[i][1]);\n";
  $js .= "}\n";
  $js .= "document.getElementById('top_chapter_list').value=current_chapter;\n";
  $js .= "document.getElementById('bottom_chapter_list').value=current_chapter;\n";
  $js .= "var current_chapter_index = document.getElementById('top_chapter_list').selectedIndex;\n";

  #文件写入类
  include_once(_CONST_LOCAL_INCLUDE_PATH."filewriter.class.php");
  FileWriter::f_xwrite($series_dir."/chapters.php", $php);
  FileWriter::f_xwrite($series_dir."/chapters.js", $js);
}

function add_log($action, $location,$value = '') {
  global $database, $user;

  $quote = array();
  $quote['action'] = string_sql($action);
  $quote['location'] = string_sql($location);
  $quote['admin_id'] = string_sql($user['buserid']);
  $quote['ip'] = string_sql($_SERVER['REMOTE_ADDR']);
  $quote['useragent'] = string_sql($_SERVER['HTTP_USER_AGENT']);
  $quote['content'] = string_sql($value);

  $database->execute("INSERT INTO admin_log (actiontime, ip, useragent, action, location, admin_id, content) VALUES (" . _CONST_TIMENOW . ", ".$quote['ip'].", ".$quote['useragent'].", ".$quote['action'].", ".$quote['location'].", ".$quote['admin_id'].", ".$quote['content'].");");
}

/*
	Paul's Simple Diff Algorithm v 0.1
	(C) Paul Butler 2007 <http://www.paulbutler.org/>
	May be used and distributed under the zlib/libpng license.

	This code is intended for learning purposes; it was written with short
	code taking priority over performance. It could be used in a practical
	application, but there are a few ways it could be optimized.

	Given two arrays, the function diff will return an array of the changes.
	I won't describe the format of the array, but it will be obvious
	if you use print_r() on the result of a diff on some test data.

	htmlDiff is a wrapper for the diff command, it takes two strings and
	returns the differences in HTML. The tags used are <ins> and <del>,
	which can easily be styled with CSS.
*/

function diff($old, $new){
	foreach($old as $oindex => $ovalue){
		$nkeys = array_keys($new, $ovalue);
		foreach($nkeys as $nindex){
			$matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
				$matrix[$oindex - 1][$nindex - 1] + 1 : 1;
			if($matrix[$oindex][$nindex] > $maxlen){
				$maxlen = $matrix[$oindex][$nindex];
				$omax = $oindex + 1 - $maxlen;
				$nmax = $nindex + 1 - $maxlen;
			}
		}
	}
	if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new));
	return array_merge(
		diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
		array_slice($new, $nmax, $maxlen),
		diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
}

function htmlDiff($old, $new){
	$diff = diff(explode(' ', $old), explode(' ', $new));
	foreach($diff as $k){
		if(is_array($k))
			$ret .= (!empty($k['d'])?"<del>".implode(' ',$k['d'])."</del> ":'').
				(!empty($k['i'])?"<ins>".implode(' ',$k['i'])."</ins> ":'');
		else $ret .= $k . ' ';
	}
	return $ret;
}

/**
 * xss漏洞
 */
function RemoveXSS($val) {
       // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
       // this prevents some character re-spacing such as <java\0script>
       // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
       $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);

       // straight replacements, the user should never need these since they're normal characters
       // this prevents like <IMG SRC=@avascript:alert('XSS')>
       $search = 'abcdefghijklmnopqrstuvwxyz';
       $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
       $search .= '1234567890!@#$%^&*()';
       $search .= '~`";:?+/={}[]-_|\'\\';
       for ($i = 0; $i < strlen($search); $i++) {
          // ;? matches the ;, which is optional
          // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars

          // @ @ search for the hex values
          $val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
          // @ @ 0{0,7} matches '0' zero to seven times
          $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
       }

       // now the only remaining whitespace attacks are \t, \n, and \r
       $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
       $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
       $ra = array_merge($ra1, $ra2);

       $found = true; // keep replacing as long as the previous round replaced something
       while ($found == true) {
          $val_before = $val;
          for ($i = 0; $i < sizeof($ra); $i++) {
             $pattern = '/';
             for ($j = 0; $j < strlen($ra[$i]); $j++) {
                if ($j > 0) {
                   $pattern .= '(';
                   $pattern .= '(&#[xX]0{0,8}([9ab]);)';
                   $pattern .= '|';
                   $pattern .= '|(&#0{0,8}([9|10|13]);)';
                   $pattern .= ')*';
                }
                $pattern .= $ra[$i][$j];
             }
             $pattern .= '/i';
             $replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
             $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
             if ($val_before == $val) {
                // no replacements were made, so exit the loop
                $found = false;
             }
          }
       }
       return $val;
}   

?>